home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcl / src-16f.lha / compiler / mips / arith.lisp < prev    next >
Encoding:
Text File  |  1992-05-19  |  25.8 KB  |  933 lines

  1. ;;; -*- Package: MIPS; Log: C.Log -*-
  2. ;;;
  3. ;;; **********************************************************************
  4. ;;; This code was written as part of the CMU Common Lisp project at
  5. ;;; Carnegie Mellon University, and has been placed in the public domain.
  6. ;;; If you want to use this code or any part of CMU Common Lisp, please contact
  7. ;;; Scott Fahlman or slisp-group@cs.cmu.edu.
  8. ;;;
  9. (ext:file-comment
  10.   "$Header: arith.lisp,v 1.45 92/03/27 19:35:24 wlott Exp $")
  11. ;;;
  12. ;;; **********************************************************************
  13. ;;;
  14. ;;; $Header: arith.lisp,v 1.45 92/03/27 19:35:24 wlott Exp $
  15. ;;;
  16. ;;;    This file contains the VM definition arithmetic VOPs for the MIPS.
  17. ;;;
  18. ;;; Written by Rob MacLachlan
  19. ;;;
  20. ;;; Converted by William Lott.
  21. ;;; 
  22.  
  23. (in-package "MIPS")
  24.  
  25.  
  26.  
  27. ;;;; Unary operations.
  28.  
  29. (define-vop (fixnum-unop)
  30.   (:args (x :scs (any-reg)))
  31.   (:results (res :scs (any-reg)))
  32.   (:note "inline fixnum arithmetic")
  33.   (:arg-types tagged-num)
  34.   (:result-types tagged-num)
  35.   (:policy :fast-safe))
  36.  
  37. (define-vop (signed-unop)
  38.   (:args (x :scs (signed-reg)))
  39.   (:results (res :scs (signed-reg)))
  40.   (:note "inline (signed-byte 32) arithmetic")
  41.   (:arg-types signed-num)
  42.   (:result-types signed-num)
  43.   (:policy :fast-safe))
  44.  
  45. (define-vop (fast-negate/fixnum fixnum-unop)
  46.   (:translate %negate)
  47.   (:generator 1
  48.     (inst subu res zero-tn x)))
  49.  
  50. (define-vop (fast-negate/signed signed-unop)
  51.   (:translate %negate)
  52.   (:generator 2
  53.     (inst subu res zero-tn x)))
  54.  
  55. (define-vop (fast-lognot/fixnum fixnum-unop)
  56.   (:temporary (:scs (any-reg) :type fixnum :to (:result 0))
  57.           temp)
  58.   (:translate lognot)
  59.   (:generator 2
  60.     (inst li temp (fixnum -1))
  61.     (inst xor res x temp)))
  62.  
  63. (define-vop (fast-lognot/signed signed-unop)
  64.   (:translate lognot)
  65.   (:generator 1
  66.     (inst nor res x zero-tn)))
  67.  
  68.  
  69.  
  70. ;;;; Binary fixnum operations.
  71.  
  72. ;;; Assume that any constant operand is the second arg...
  73.  
  74. (define-vop (fast-fixnum-binop)
  75.   (:args (x :target r :scs (any-reg))
  76.      (y :target r :scs (any-reg)))
  77.   (:arg-types tagged-num tagged-num)
  78.   (:results (r :scs (any-reg)))
  79.   (:result-types tagged-num)
  80.   (:note "inline fixnum arithmetic")
  81.   (:effects)
  82.   (:affected)
  83.   (:policy :fast-safe))
  84.  
  85. (define-vop (fast-unsigned-binop)
  86.   (:args (x :target r :scs (unsigned-reg))
  87.      (y :target r :scs (unsigned-reg)))
  88.   (:arg-types unsigned-num unsigned-num)
  89.   (:results (r :scs (unsigned-reg)))
  90.   (:result-types unsigned-num)
  91.   (:note "inline (unsigned-byte 32) arithmetic")
  92.   (:effects)
  93.   (:affected)
  94.   (:policy :fast-safe))
  95.  
  96. (define-vop (fast-signed-binop)
  97.   (:args (x :target r :scs (signed-reg))
  98.      (y :target r :scs (signed-reg)))
  99.   (:arg-types signed-num signed-num)
  100.   (:results (r :scs (signed-reg)))
  101.   (:result-types signed-num)
  102.   (:note "inline (signed-byte 32) arithmetic")
  103.   (:effects)
  104.   (:affected)
  105.   (:policy :fast-safe))
  106.  
  107. (defmacro define-binop (translate cost op &optional unsigned)
  108.   `(progn
  109.      (define-vop (,(intern (concatenate 'simple-string
  110.                     "FAST-"
  111.                     (string translate)
  112.                     "/FIXNUM=>FIXNUM"))
  113.           fast-fixnum-binop)
  114.        (:args (x :target r
  115.          :scs (any-reg))
  116.           (y :target r
  117.          :scs (any-reg immediate zero
  118.                    ,(if unsigned
  119.                     'unsigned-immediate
  120.                     'negative-immediate))))
  121.        (:translate ,translate)
  122.        (:generator ,cost
  123.      (inst ,op r x
  124.            (sc-case y
  125.          (any-reg y)
  126.          (zero zero-tn)
  127.          ((immediate
  128.            ,(if unsigned 'unsigned-immediate 'negative-immediate))
  129.           (fixnum (tn-value y)))))))
  130.      (define-vop (,(intern (concatenate 'simple-string
  131.                     "FAST-"
  132.                     (string translate)
  133.                     "/SIGNED=>SIGNED"))
  134.           fast-signed-binop)
  135.        (:args (x :target r
  136.          :scs (signed-reg))
  137.           (y :target r
  138.          :scs (signed-reg immediate zero
  139.                   ,(if unsigned
  140.                        'unsigned-immediate
  141.                        'negative-immediate))))
  142.        (:translate ,translate)
  143.        (:generator ,(1+ cost)
  144.      (inst ,op r x
  145.            (sc-case y
  146.          (signed-reg y)
  147.          (zero zero-tn)
  148.          ((immediate
  149.            ,(if unsigned 'unsigned-immediate 'negative-immediate))
  150.           (tn-value y))))))
  151.      (define-vop (,(intern (concatenate 'simple-string
  152.                     "FAST-"
  153.                     (string translate)
  154.                     "/UNSIGNED=>UNSIGNED"))
  155.           fast-unsigned-binop)
  156.        (:args (x :target r
  157.          :scs (unsigned-reg))
  158.           (y :target r
  159.          :scs (unsigned-reg immediate zero
  160.                     ,(if unsigned
  161.                      'unsigned-immediate
  162.                      'negative-immediate))))
  163.        (:translate ,translate)
  164.        (:generator ,(1+ cost)
  165.      (inst ,op r x
  166.            (sc-case y
  167.          (unsigned-reg y)
  168.          (zero zero-tn)
  169.          ((immediate
  170.            ,(if unsigned 'unsigned-immediate 'negative-immediate))
  171.           (tn-value y))))))))
  172.  
  173. (define-binop + 2 addu)
  174. (define-binop - 2 subu)
  175. (define-binop logior 1 or t)
  176. (define-binop logand 1 and t)
  177. (define-binop logxor 1 xor t)
  178.  
  179. ;;; Special case fixnum + and - that don't check for overflow.  Useful when we
  180. ;;; know the output type is a fixnum.
  181.  
  182. (define-vop (fast-+/fixnum fast-+/fixnum=>fixnum)
  183.   (:results (r :scs (any-reg descriptor-reg)))
  184.   (:result-types (:or signed-num unsigned-num))
  185.   (:note nil)
  186.   (:generator 1
  187.     (inst add r x
  188.       (sc-case y
  189.         (any-reg y)
  190.         (zero zero-tn)
  191.         ((immediate negative-immediate)
  192.          (fixnum (tn-value y)))))))
  193.  
  194. (define-vop (fast--/fixnum fast--/fixnum=>fixnum)
  195.   (:results (r :scs (any-reg descriptor-reg)))
  196.   (:result-types (:or signed-num unsigned-num))
  197.   (:note nil)
  198.   (:generator 1
  199.     (inst sub r x
  200.       (sc-case y
  201.         (any-reg y)
  202.         (zero zero-tn)
  203.         ((immediate negative-immediate)
  204.          (fixnum (tn-value y)))))))
  205.  
  206.  
  207. ;;; Shifting
  208.  
  209. (define-vop (fast-ash)
  210.   (:note "inline ASH")
  211.   (:args (number :scs (signed-reg unsigned-reg) :to :save)
  212.      (amount :scs (signed-reg immediate negative-immediate)))
  213.   (:arg-types (:or signed-num unsigned-num) signed-num)
  214.   (:results (result :scs (signed-reg unsigned-reg)))
  215.   (:result-types (:or signed-num unsigned-num))
  216.   (:translate ash)
  217.   (:policy :fast-safe)
  218.   (:temporary (:sc non-descriptor-reg) ndesc)
  219.   (:temporary (:sc non-descriptor-reg :to :eval) temp)
  220.   (:generator 3
  221.     (sc-case amount
  222.       (signed-reg
  223.        (let ((positive (gen-label))
  224.          (done (gen-label)))
  225.      (inst bgez amount positive)
  226.      (inst subu ndesc zero-tn amount)
  227.      (inst slt temp ndesc 31)
  228.      (inst bne temp zero-tn done)
  229.      (sc-case number
  230.        (signed-reg (inst sra result number ndesc))
  231.        (unsigned-reg (inst srl result number ndesc)))
  232.      (inst b done)
  233.      (sc-case number
  234.        (signed-reg (inst sra result number 31))
  235.        (unsigned-reg (inst srl result number 31)))
  236.  
  237.      (emit-label positive)
  238.      ;; The result-type assures us that this shift will not overflow.
  239.      (inst sll result number amount)
  240.  
  241.      (emit-label done)))
  242.  
  243.       ((immediate negative-immediate)
  244.        (let ((amount (tn-value amount)))
  245.      (if (minusp amount)
  246.          (sc-case number
  247.            (unsigned-reg
  248.         (inst srl result number (- amount)))
  249.            (t
  250.         (inst sra result number (- amount))))
  251.          (inst sll result number amount)))))))
  252.  
  253.  
  254.  
  255. (define-vop (signed-byte-32-len)
  256.   (:translate integer-length)
  257.   (:note "inline (signed-byte 32) integer-length")
  258.   (:policy :fast-safe)
  259.   (:args (arg :scs (signed-reg) :target shift))
  260.   (:arg-types signed-num)
  261.   (:results (res :scs (any-reg)))
  262.   (:result-types positive-fixnum)
  263.   (:temporary (:scs (non-descriptor-reg) :from (:argument 0)) shift)
  264.   (:generator 30
  265.     (let ((loop (gen-label))
  266.       (test (gen-label)))
  267.       (move shift arg)
  268.       (inst bgez shift test)
  269.       (move res zero-tn)
  270.       (inst b test)
  271.       (inst nor shift shift)
  272.  
  273.       (emit-label loop)
  274.       (inst add res (fixnum 1))
  275.       
  276.       (emit-label test)
  277.       (inst bne shift loop)
  278.       (inst srl shift 1))))
  279.  
  280. (define-vop (unsigned-byte-32-count)
  281.   (:translate logcount)
  282.   (:note "inline (unsigned-byte 32) logcount")
  283.   (:policy :fast-safe)
  284.   (:args (arg :scs (unsigned-reg) :target num))
  285.   (:arg-types unsigned-num)
  286.   (:results (res :scs (unsigned-reg)))
  287.   (:result-types positive-fixnum)
  288.   (:temporary (:scs (non-descriptor-reg) :from (:argument 0) :to (:result 0)
  289.             :target res) num)
  290.   (:temporary (:scs (non-descriptor-reg)) mask temp)
  291.   (:generator 30
  292.     (inst li mask #x55555555)
  293.     (inst srl temp arg 1)
  294.     (inst and num arg mask)
  295.     (inst and temp mask)
  296.     (inst addu num temp)
  297.     (inst li mask #x33333333)
  298.     (inst srl temp num 2)
  299.     (inst and num mask)
  300.     (inst and temp mask)
  301.     (inst addu num temp)
  302.     (inst li mask #x0f0f0f0f)
  303.     (inst srl temp num 4)
  304.     (inst and num mask)
  305.     (inst and temp mask)
  306.     (inst addu num temp)
  307.     (inst li mask #x00ff00ff)
  308.     (inst srl temp num 8)
  309.     (inst and num mask)
  310.     (inst and temp mask)
  311.     (inst addu num temp)
  312.     (inst li mask #x0000ffff)
  313.     (inst srl temp num 16)
  314.     (inst and num mask)
  315.     (inst and temp mask)
  316.     (inst addu res num temp)))
  317.  
  318.  
  319. ;;; Multiply and Divide.
  320.  
  321. (define-vop (fast-*/fixnum=>fixnum fast-fixnum-binop)
  322.   (:temporary (:scs (non-descriptor-reg) :type random) temp)
  323.   (:translate *)
  324.   (:generator 4
  325.     (inst sra temp y 2)
  326.     (inst mult x temp)
  327.     (inst mflo r)))
  328.  
  329. (define-vop (fast-*/signed=>signed fast-signed-binop)
  330.   (:translate *)
  331.   (:generator 3
  332.     (inst mult x y)
  333.     (inst mflo r)))
  334.  
  335. (define-vop (fast-*/unsigned=>unsigned fast-unsigned-binop)
  336.   (:translate *)
  337.   (:generator 3
  338.     (inst multu x y)
  339.     (inst mflo r)))
  340.  
  341.  
  342.  
  343. (define-vop (fast-truncate/fixnum fast-fixnum-binop)
  344.   (:translate truncate)
  345.   (:results (q :scs (any-reg))
  346.         (r :scs (any-reg)))
  347.   (:result-types tagged-num tagged-num)
  348.   (:temporary (:scs (non-descriptor-reg) :to :eval) temp)
  349.   (:vop-var vop)
  350.   (:save-p :compute-only)
  351.   (:generator 11
  352.     (let ((zero (generate-error-code vop division-by-zero-error x y)))
  353.       (inst beq y zero-tn zero))
  354.     (inst div x y)
  355.     (inst mflo temp)
  356.     (inst sll q temp 2)
  357.     (inst mfhi r)))
  358.  
  359. (define-vop (fast-truncate/unsigned fast-unsigned-binop)
  360.   (:translate truncate)
  361.   (:results (q :scs (unsigned-reg))
  362.         (r :scs (unsigned-reg)))
  363.   (:result-types unsigned-num unsigned-num)
  364.   (:vop-var vop)
  365.   (:save-p :compute-only)
  366.   (:generator 12
  367.     (let ((zero (generate-error-code vop division-by-zero-error x y)))
  368.       (inst beq y zero-tn zero))
  369.     (inst divu x y)
  370.     (inst mflo q)
  371.     (inst mfhi r)))
  372.  
  373. (define-vop (fast-truncate/signed fast-signed-binop)
  374.   (:translate truncate)
  375.   (:results (q :scs (signed-reg))
  376.         (r :scs (signed-reg)))
  377.   (:result-types signed-num signed-num)
  378.   (:vop-var vop)
  379.   (:save-p :compute-only)
  380.   (:generator 12
  381.     (let ((zero (generate-error-code vop division-by-zero-error x y)))
  382.       (inst beq y zero-tn zero))
  383.     (inst div x y)
  384.     (inst mflo q)
  385.     (inst mfhi r)))
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392. ;;;; Binary conditional VOPs:
  393.  
  394. (define-vop (fast-conditional)
  395.   (:conditional)
  396.   (:info target not-p)
  397.   (:effects)
  398.   (:affected)
  399.   (:temporary (:scs (non-descriptor-reg)) temp)
  400.   (:policy :fast-safe))
  401.  
  402. (deftype integer-with-a-bite-out (s bite)
  403.   (cond ((eq s '*) 'integer)
  404.     ((and (integerp s) (> s 1))
  405.      (let ((bound (ash 1 (1- s))))
  406.        `(integer ,(- bound) ,(- bound bite 1))))
  407.     (t
  408.      (error "Bad size specified for SIGNED-BYTE type specifier: ~S." s))))
  409.  
  410. (define-vop (fast-conditional/fixnum fast-conditional)
  411.   (:args (x :scs (any-reg))
  412.      (y :scs (any-reg)))
  413.   (:arg-types tagged-num tagged-num)
  414.   (:note "inline fixnum comparison"))
  415.  
  416. (define-vop (fast-conditional-c/fixnum fast-conditional/fixnum)
  417.   (:args (x :scs (any-reg)))
  418.   (:arg-types tagged-num (:constant (integer-with-a-bite-out 14 #.(fixnum 1))))
  419.   (:info target not-p y))
  420.  
  421. (define-vop (fast-conditional/signed fast-conditional)
  422.   (:args (x :scs (signed-reg))
  423.      (y :scs (signed-reg)))
  424.   (:arg-types signed-num signed-num)
  425.   (:note "inline (signed-byte 32) comparison"))
  426.  
  427. (define-vop (fast-conditional-c/signed fast-conditional/signed)
  428.   (:args (x :scs (signed-reg)))
  429.   (:arg-types signed-num (:constant (integer-with-a-bite-out 16 1)))
  430.   (:info target not-p y))
  431.  
  432. (define-vop (fast-conditional/unsigned fast-conditional)
  433.   (:args (x :scs (unsigned-reg))
  434.      (y :scs (unsigned-reg)))
  435.   (:arg-types unsigned-num unsigned-num)
  436.   (:note "inline (unsigned-byte 32) comparison"))
  437.  
  438. (define-vop (fast-conditional-c/unsigned fast-conditional/unsigned)
  439.   (:args (x :scs (unsigned-reg)))
  440.   (:arg-types unsigned-num (:constant (and (integer-with-a-bite-out 16 1)
  441.                        unsigned-byte)))
  442.   (:info target not-p y))
  443.  
  444.  
  445. (defmacro define-conditional-vop (translate &rest generator)
  446.   ;;
  447.   ;; Squelch dead-code notes...
  448.   `(;locally (declare (optimize (inhibit-warnings 3)))
  449.     progn ; but not really, since that makes a big function, which doesn't load.
  450.      ,@(mapcar #'(lambda (suffix cost signed)
  451.            (unless (and (member suffix '(/fixnum -c/fixnum))
  452.                 (eq translate 'eql))
  453.              `(define-vop (,(intern (format nil "~:@(FAST-IF-~A~A~)"
  454.                             translate suffix))
  455.                    ,(intern
  456.                      (format nil "~:@(FAST-CONDITIONAL~A~)"
  457.                          suffix)))
  458.             (:translate ,translate)
  459.             (:generator ,cost
  460.               (let* ((signed ,signed)
  461.                  (-c/fixnum ,(eq suffix '-c/fixnum))
  462.                  (y (if -c/fixnum (fixnum y) y)))
  463.                 ,@generator)))))
  464.            '(/fixnum -c/fixnum /signed -c/signed /unsigned -c/unsigned)
  465.            '(3 2 5 4 5 4)
  466.            '(t t t t nil nil))))
  467.  
  468. (define-conditional-vop <
  469.   (cond ((and signed (eql y 0))
  470.      (if not-p
  471.          (inst bgez x target)
  472.          (inst bltz x target)))
  473.     (t
  474.      (if signed
  475.          (inst slt temp x y)
  476.          (inst sltu temp x y))
  477.      (if not-p
  478.          (inst beq temp zero-tn target)
  479.          (inst bne temp zero-tn target))))
  480.   (inst nop))
  481.  
  482. (define-conditional-vop >
  483.   (cond ((and signed (eql y 0))
  484.      (if not-p
  485.          (inst blez x target)
  486.          (inst bgtz x target)))
  487.     ((integerp y)
  488.      (let ((y (+ y (if -c/fixnum (fixnum 1) 1))))
  489.        (if signed
  490.            (inst slt temp x y)
  491.            (inst sltu temp x y))
  492.        (if not-p
  493.            (inst bne temp zero-tn target)
  494.            (inst beq temp zero-tn target))))
  495.     (t
  496.      (if signed
  497.          (inst slt temp y x)
  498.          (inst sltu temp y x))
  499.      (if not-p
  500.          (inst beq temp zero-tn target)
  501.          (inst bne temp zero-tn target))))
  502.   (inst nop))
  503.  
  504. ;;; EQL/FIXNUM is funny because the first arg can be of any type, not just a
  505. ;;; known fixnum.
  506.  
  507. (define-conditional-vop eql
  508.   (declare (ignore signed))
  509.   (when (integerp y)
  510.     (inst li temp y)
  511.     (setf y temp))
  512.   (if not-p
  513.       (inst bne x y target)
  514.       (inst beq x y target))
  515.   (inst nop))
  516.  
  517. ;;; These versions specify a fixnum restriction on their first arg.  We have
  518. ;;; also generic-eql/fixnum VOPs which are the same, but have no restriction on
  519. ;;; the first arg and a higher cost.  The reason for doing this is to prevent
  520. ;;; fixnum specific operations from being used on word integers, spuriously
  521. ;;; consing the argument.
  522. ;;;
  523. (define-vop (fast-eql/fixnum fast-conditional)
  524.   (:args (x :scs (any-reg descriptor-reg))
  525.      (y :scs (any-reg)))
  526.   (:arg-types tagged-num tagged-num)
  527.   (:note "inline fixnum comparison")
  528.   (:translate eql)
  529.   (:ignore temp)
  530.   (:generator 3
  531.     (if not-p
  532.     (inst bne x y target)
  533.     (inst beq x y target))
  534.     (inst nop)))
  535. ;;;
  536. (define-vop (generic-eql/fixnum fast-eql/fixnum)
  537.   (:arg-types * tagged-num)
  538.   (:variant-cost 7))
  539.  
  540. (define-vop (fast-eql-c/fixnum fast-conditional/fixnum)
  541.   (:args (x :scs (any-reg descriptor-reg)))
  542.   (:arg-types tagged-num (:constant (signed-byte 14)))
  543.   (:info target not-p y)
  544.   (:translate eql)
  545.   (:generator 2
  546.     (let ((y (cond ((eql y 0) zero-tn)
  547.            (t
  548.             (inst li temp (fixnum y))
  549.             temp))))
  550.       (if not-p
  551.       (inst bne x y target)
  552.       (inst beq x y target))
  553.       (inst nop))))
  554. ;;;
  555. (define-vop (generic-eql-c/fixnum fast-eql-c/fixnum)
  556.   (:arg-types * (:constant (signed-byte 14)))
  557.   (:variant-cost 6))
  558.   
  559.  
  560. ;;;; 32-bit logical operations
  561.  
  562. (define-vop (merge-bits)
  563.   (:translate merge-bits)
  564.   (:args (shift :scs (signed-reg unsigned-reg))
  565.      (prev :scs (unsigned-reg))
  566.      (next :scs (unsigned-reg)))
  567.   (:arg-types tagged-num unsigned-num unsigned-num)
  568.   (:temporary (:scs (unsigned-reg) :to (:result 0)) temp)
  569.   (:temporary (:scs (unsigned-reg) :to (:result 0) :target result) res)
  570.   (:results (result :scs (unsigned-reg)))
  571.   (:result-types unsigned-num)
  572.   (:policy :fast-safe)
  573.   (:generator 4
  574.     (let ((done (gen-label)))
  575.       (inst beq shift done)
  576.       (inst srl res next shift)
  577.       (inst subu temp zero-tn shift)
  578.       (inst sll temp prev temp)
  579.       (inst or res res temp)
  580.       (emit-label done)
  581.       (move result res))))
  582.  
  583.  
  584. (define-vop (32bit-logical)
  585.   (:args (x :scs (unsigned-reg))
  586.      (y :scs (unsigned-reg)))
  587.   (:arg-types unsigned-num unsigned-num)
  588.   (:results (r :scs (unsigned-reg)))
  589.   (:result-types unsigned-num)
  590.   (:policy :fast-safe))
  591.  
  592. (define-vop (32bit-logical-not 32bit-logical)
  593.   (:translate 32bit-logical-not)
  594.   (:args (x :scs (unsigned-reg)))
  595.   (:arg-types unsigned-num)
  596.   (:generator 1
  597.     (inst nor r x zero-tn)))
  598.  
  599. (define-vop (32bit-logical-and 32bit-logical)
  600.   (:translate 32bit-logical-and)
  601.   (:generator 1
  602.     (inst and r x y)))
  603.  
  604. (deftransform 32bit-logical-nand ((x y) (* *))
  605.   '(32bit-logical-not (32bit-logical-and x y)))
  606.  
  607. (define-vop (32bit-logical-or 32bit-logical)
  608.   (:translate 32bit-logical-or)
  609.   (:generator 1
  610.     (inst or r x y)))
  611.  
  612. (define-vop (32bit-logical-nor 32bit-logical)
  613.   (:translate 32bit-logical-nor)
  614.   (:generator 1
  615.     (inst nor r x y)))
  616.  
  617. (define-vop (32bit-logical-xor 32bit-logical)
  618.   (:translate 32bit-logical-xor)
  619.   (:generator 1
  620.     (inst xor r x y)))
  621.  
  622. (deftransform 32bit-logical-eqv ((x y) (* *))
  623.   '(32bit-logical-not (32bit-logical-xor x y)))
  624.  
  625. (deftransform 32bit-logical-andc1 ((x y) (* *))
  626.   '(32bit-logical-and (32bit-logical-not x) y))
  627.  
  628. (deftransform 32bit-logical-andc2 ((x y) (* *))
  629.   '(32bit-logical-and x (32bit-logical-not y)))
  630.  
  631. (deftransform 32bit-logical-orc1 ((x y) (* *))
  632.   '(32bit-logical-or (32bit-logical-not x) y))
  633.  
  634. (deftransform 32bit-logical-orc2 ((x y) (* *))
  635.   '(32bit-logical-or x (32bit-logical-not y)))
  636.  
  637.  
  638. (define-vop (shift-towards-someplace)
  639.   (:policy :fast-safe)
  640.   (:args (num :scs (unsigned-reg))
  641.      (amount :scs (signed-reg)))
  642.   (:arg-types unsigned-num tagged-num)
  643.   (:results (r :scs (unsigned-reg)))
  644.   (:result-types unsigned-num))
  645.  
  646. (define-vop (shift-towards-start shift-towards-someplace)
  647.   (:translate shift-towards-start)
  648.   (:note "SHIFT-TOWARDS-START")
  649.   (:generator 1
  650.     (ecase (backend-byte-order *backend*)
  651.       (:big-endian
  652.        (inst sll r num amount))
  653.       (:little-endian
  654.        (inst srl r num amount)))))
  655.  
  656. (define-vop (shift-towards-end shift-towards-someplace)
  657.   (:translate shift-towards-end)
  658.   (:note "SHIFT-TOWARDS-END")
  659.   (:generator 1
  660.     (ecase (backend-byte-order *backend*)
  661.       (:big-endian
  662.        (inst srl r num amount))
  663.       (:little-endian
  664.        (inst sll r num amount)))))
  665.  
  666.  
  667.  
  668. ;;;; Bignum stuff.
  669.  
  670. (define-vop (bignum-length get-header-data)
  671.   (:translate bignum::%bignum-length)
  672.   (:policy :fast-safe))
  673.  
  674. (define-vop (bignum-set-length set-header-data)
  675.   (:translate bignum::%bignum-set-length)
  676.   (:policy :fast-safe))
  677.  
  678. (define-vop (bignum-ref word-index-ref)
  679.   (:variant vm:bignum-digits-offset vm:other-pointer-type)
  680.   (:translate bignum::%bignum-ref)
  681.   (:results (value :scs (unsigned-reg)))
  682.   (:result-types unsigned-num))
  683.  
  684. (define-vop (bignum-set word-index-set)
  685.   (:variant vm:bignum-digits-offset vm:other-pointer-type)
  686.   (:translate bignum::%bignum-set)
  687.   (:args (object :scs (descriptor-reg))
  688.      (index :scs (any-reg immediate zero negative-immediate))
  689.      (value :scs (unsigned-reg)))
  690.   (:arg-types t positive-fixnum unsigned-num)
  691.   (:results (result :scs (unsigned-reg)))
  692.   (:result-types unsigned-num))
  693.  
  694. (define-vop (digit-0-or-plus)
  695.   (:translate bignum::%digit-0-or-plusp)
  696.   (:policy :fast-safe)
  697.   (:args (digit :scs (unsigned-reg)))
  698.   (:arg-types unsigned-num)
  699.   (:results (result :scs (descriptor-reg)))
  700.   (:generator 3
  701.     (let ((done (gen-label)))
  702.       (inst bltz digit done)
  703.       (move result null-tn)
  704.       (load-symbol result 't)
  705.       (emit-label done))))
  706.  
  707. (define-vop (add-w/carry)
  708.   (:translate bignum::%add-with-carry)
  709.   (:policy :fast-safe)
  710.   (:args (a :scs (unsigned-reg))
  711.      (b :scs (unsigned-reg))
  712.      (c :scs (any-reg)))
  713.   (:arg-types unsigned-num unsigned-num positive-fixnum)
  714.   (:temporary (:scs (unsigned-reg) :to (:result 0) :target result) res)
  715.   (:results (result :scs (unsigned-reg))
  716.         (carry :scs (unsigned-reg) :from :eval))
  717.   (:result-types unsigned-num positive-fixnum)
  718.   (:temporary (:scs (non-descriptor-reg)) temp)
  719.   (:generator 5
  720.     (let ((carry-in (gen-label))
  721.       (done (gen-label)))
  722.       (inst bne c carry-in)
  723.       (inst addu res a b)
  724.  
  725.       (inst b done)
  726.       (inst sltu carry res b)
  727.  
  728.       (emit-label carry-in)
  729.       (inst addu res 1)
  730.       (inst nor temp a zero-tn)
  731.       (inst sltu carry b temp)
  732.       (inst xor carry 1)
  733.  
  734.       (emit-label done)
  735.       (move result res))))
  736.  
  737. (define-vop (sub-w/borrow)
  738.   (:translate bignum::%subtract-with-borrow)
  739.   (:policy :fast-safe)
  740.   (:args (a :scs (unsigned-reg))
  741.      (b :scs (unsigned-reg))
  742.      (c :scs (any-reg)))
  743.   (:arg-types unsigned-num unsigned-num positive-fixnum)
  744.   (:temporary (:scs (unsigned-reg) :to (:result 0) :target result) res)
  745.   (:results (result :scs (unsigned-reg))
  746.         (borrow :scs (unsigned-reg) :from :eval))
  747.   (:result-types unsigned-num positive-fixnum)
  748.   (:generator 4
  749.     (let ((no-borrow-in (gen-label))
  750.       (done (gen-label)))
  751.  
  752.       (inst bne c no-borrow-in)
  753.       (inst subu res a b)
  754.  
  755.       (inst subu res 1)
  756.       (inst b done)
  757.       (inst sltu borrow b a)
  758.  
  759.       (emit-label no-borrow-in)
  760.       (inst sltu borrow a b)
  761.       (inst xor borrow 1)
  762.  
  763.       (emit-label done)
  764.       (move result res))))
  765.  
  766. (define-vop (bignum-mult-and-add-3-arg)
  767.   (:translate bignum::%multiply-and-add)
  768.   (:policy :fast-safe)
  769.   (:args (x :scs (unsigned-reg))
  770.      (y :scs (unsigned-reg))
  771.      (carry-in :scs (unsigned-reg) :to :save))
  772.   (:arg-types unsigned-num unsigned-num unsigned-num)
  773.   (:temporary (:scs (unsigned-reg) :from (:argument 1)) temp)
  774.   (:results (hi :scs (unsigned-reg))
  775.         (lo :scs (unsigned-reg)))
  776.   (:result-types unsigned-num unsigned-num)
  777.   (:generator 6
  778.     (inst multu x y)
  779.     (inst mflo temp)
  780.     (inst addu lo temp carry-in)
  781.     (inst sltu temp lo carry-in)
  782.     (inst mfhi hi)
  783.     (inst addu hi temp)))
  784.  
  785. (define-vop (bignum-mult-and-add-4-arg)
  786.   (:translate bignum::%multiply-and-add)
  787.   (:policy :fast-safe)
  788.   (:args (x :scs (unsigned-reg))
  789.      (y :scs (unsigned-reg))
  790.      (prev :scs (unsigned-reg))
  791.      (carry-in :scs (unsigned-reg) :to :save))
  792.   (:arg-types unsigned-num unsigned-num unsigned-num unsigned-num)
  793.   (:temporary (:scs (unsigned-reg) :from (:argument 2)) temp)
  794.   (:results (hi :scs (unsigned-reg))
  795.         (lo :scs (unsigned-reg)))
  796.   (:result-types unsigned-num unsigned-num)
  797.   (:generator 9
  798.     (inst multu x y)
  799.     (inst addu lo prev carry-in)
  800.     (inst sltu temp lo carry-in)
  801.     (inst mfhi hi)
  802.     (inst addu hi temp)
  803.     (inst mflo temp)
  804.     (inst addu lo temp)
  805.     (inst sltu temp lo temp)
  806.     (inst addu hi temp)))
  807.  
  808. (define-vop (bignum-mult)
  809.   (:translate bignum::%multiply)
  810.   (:policy :fast-safe)
  811.   (:args (x :scs (unsigned-reg))
  812.      (y :scs (unsigned-reg)))
  813.   (:arg-types unsigned-num unsigned-num)
  814.   (:results (hi :scs (unsigned-reg))
  815.         (lo :scs (unsigned-reg)))
  816.   (:result-types unsigned-num unsigned-num)
  817.   (:generator 3
  818.     (inst multu x y)
  819.     (inst mflo lo)
  820.     (inst mfhi hi)))
  821.  
  822. (define-vop (bignum-lognot)
  823.   (:translate bignum::%lognot)
  824.   (:policy :fast-safe)
  825.   (:args (x :scs (unsigned-reg)))
  826.   (:arg-types unsigned-num)
  827.   (:results (r :scs (unsigned-reg)))
  828.   (:result-types unsigned-num)
  829.   (:generator 1
  830.     (inst nor r x zero-tn)))
  831.  
  832. (define-vop (fixnum-to-digit)
  833.   (:translate bignum::%fixnum-to-digit)
  834.   (:policy :fast-safe)
  835.   (:args (fixnum :scs (any-reg)))
  836.   (:arg-types tagged-num)
  837.   (:results (digit :scs (unsigned-reg)))
  838.   (:result-types unsigned-num)
  839.   (:generator 1
  840.     (inst sra digit fixnum 2)))
  841.  
  842. (define-vop (bignum-floor)
  843.   (:translate bignum::%floor)
  844.   (:policy :fast-safe)
  845.   (:args (num-high :scs (unsigned-reg) :target rem)
  846.      (num-low :scs (unsigned-reg) :target rem-low)
  847.      (denom :scs (unsigned-reg) :to (:eval 1)))
  848.   (:arg-types unsigned-num unsigned-num unsigned-num)
  849.   (:temporary (:scs (unsigned-reg) :from (:argument 1)) rem-low)
  850.   (:temporary (:scs (unsigned-reg) :from (:eval 0)) temp)
  851.   (:results (quo :scs (unsigned-reg) :from (:eval 0))
  852.         (rem :scs (unsigned-reg) :from (:argument 0)))
  853.   (:result-types unsigned-num unsigned-num)
  854.   (:generator 325 ; number of inst assuming targeting works.
  855.     (move rem num-high)
  856.     (move rem-low num-low)
  857.     (flet ((maybe-subtract (&optional (guess temp))
  858.          (inst subu temp guess 1)
  859.          (inst and temp denom)
  860.          (inst subu rem temp)))
  861.       (inst sltu quo rem denom)
  862.       (maybe-subtract quo)
  863.       (dotimes (i 32)
  864.     (inst sll rem 1)
  865.     (inst srl temp rem-low 31)
  866.     (inst or rem temp)
  867.     (inst sll rem-low 1)
  868.     (inst sltu temp rem denom)
  869.     (inst sll quo 1)
  870.     (inst or quo temp)
  871.     (maybe-subtract)))
  872.     (inst nor quo zero-tn)))
  873.  
  874. (define-vop (signify-digit)
  875.   (:translate bignum::%fixnum-digit-with-correct-sign)
  876.   (:policy :fast-safe)
  877.   (:args (digit :scs (unsigned-reg) :target res))
  878.   (:arg-types unsigned-num)
  879.   (:results (res :scs (any-reg signed-reg)))
  880.   (:result-types signed-num)
  881.   (:generator 1
  882.     (sc-case res
  883.       (any-reg
  884.        (inst sll res digit 2))
  885.       (signed-reg
  886.        (move res digit)))))
  887.  
  888.  
  889. (define-vop (digit-ashr)
  890.   (:translate bignum::%ashr)
  891.   (:policy :fast-safe)
  892.   (:args (digit :scs (unsigned-reg))
  893.      (count :scs (unsigned-reg)))
  894.   (:arg-types unsigned-num positive-fixnum)
  895.   (:results (result :scs (unsigned-reg)))
  896.   (:result-types unsigned-num)
  897.   (:generator 1
  898.     (inst sra result digit count)))
  899.  
  900. (define-vop (digit-lshr digit-ashr)
  901.   (:translate bignum::%digit-logical-shift-right)
  902.   (:generator 1
  903.     (inst srl result digit count)))
  904.  
  905. (define-vop (digit-ashl digit-ashr)
  906.   (:translate bignum::%ashl)
  907.   (:generator 1
  908.     (inst sll result digit count)))
  909.  
  910.  
  911. ;;;; Static functions.
  912.  
  913. (define-static-function two-arg-gcd (x y) :translate gcd)
  914. (define-static-function two-arg-lcm (x y) :translate lcm)
  915.  
  916. (define-static-function two-arg-+ (x y) :translate +)
  917. (define-static-function two-arg-- (x y) :translate -)
  918. (define-static-function two-arg-* (x y) :translate *)
  919. (define-static-function two-arg-/ (x y) :translate /)
  920.  
  921. (define-static-function two-arg-< (x y) :translate <)
  922. (define-static-function two-arg-<= (x y) :translate <=)
  923. (define-static-function two-arg-> (x y) :translate >)
  924. (define-static-function two-arg->= (x y) :translate >=)
  925. (define-static-function two-arg-= (x y) :translate =)
  926. (define-static-function two-arg-/= (x y) :translate /=)
  927.  
  928. (define-static-function %negate (x) :translate %negate)
  929.  
  930. (define-static-function two-arg-and (x y) :translate logand)
  931. (define-static-function two-arg-ior (x y) :translate logior)
  932. (define-static-function two-arg-xor (x y) :translate logxor)
  933.